package ldh.fx.adminfx.util;

import java.io.IOException;
import java.net.URI;
import java.net.URLEncoder;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.nio.charset.Charset;
import java.time.Duration;
import java.util.Map;
import java.util.stream.Collectors;

public class HttpClientUtil {

    public static String get(String url) throws IOException, InterruptedException {
        HttpResponse<String> response = get(url, null, 50, 50);
        return response.body();
    }

    public static String get(String url, Map<String, Object> params) throws IOException, InterruptedException {
        HttpResponse<String> response = get(url, params, 50, 50);
        return response.body();
    }

    public static HttpResponse<String> get(String url, Map<String, Object> params, long connectionTime, long timeout) throws IOException, InterruptedException {
        HttpClient httpClient = buildHttpClient(connectionTime);
        url = urlConcatParams(url, params);
        //2.set read timeout
        HttpRequest request = HttpRequest.newBuilder()
                .uri(URI.create(url))
                .header("Content-Type","application/x-www-form-urlencoded")
                .timeout(Duration.ofMillis(timeout))
                .build();

        HttpResponse<String> response = httpClient.send(request, HttpResponse.BodyHandlers.ofString());
        return response;
    }

    public static HttpResponse<String> post(String url, Map<String, Object> params) throws IOException, InterruptedException {
        return post(url, params, 50, 50);
    }

    public static HttpResponse<String> post(String url, Map<String, Object> params, long connectionTime, long timeout) throws IOException, InterruptedException {
        HttpClient client = buildHttpClient(connectionTime);

        String paramStr = paramsToString(params);
        HttpRequest request = HttpRequest.newBuilder()
                .uri(URI.create(url))
                .timeout(Duration.ofMillis(timeout))
                .header("Content-Type","application/x-www-form-urlencoded")
                .POST(HttpRequest.BodyPublishers.ofString(paramStr))
                .build();

        HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
        return response;
    }

    public static HttpResponse<String> body(String url, Map<String, Object> params) throws IOException, InterruptedException {
        return post(url, params, 50, 50);
    }

    public static HttpResponse<String> body(String url, Map<String, Object> params, long connectionTime, long timeout) throws IOException, InterruptedException {
        HttpClient client = buildHttpClient(connectionTime);

        String paramStr = paramsToString(params);
        HttpRequest request = HttpRequest.newBuilder()
                .uri(URI.create(url))
                .timeout(Duration.ofMillis(timeout))
                .header("Content-Type", "application/json")
                .POST(HttpRequest.BodyPublishers.ofString(paramStr))
                .build();

        HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
        return response;
    }

    private static HttpClient buildHttpClient(long connectionTime) {
        HttpClient client = HttpClient.newBuilder()
                .connectTimeout(Duration.ofSeconds(connectionTime))
                .followRedirects(HttpClient.Redirect.NORMAL)
                .build();
        return client;
    }

    private static String paramsToString(Map<String, Object> params) {
        String paramStr = params != null ? params.entrySet().stream().map(entry->
                entry.getKey() + "=" + URLEncoder.encode(entry.getValue().toString(), Charset.forName("utf8"))).collect(Collectors.joining("&")) : "";
        return paramStr;
    }

    private static String urlConcatParams(String url, Map<String, Object> params) {
        String paramStr = paramsToString(params);
        String splitChar = url.contains("?") ? "&" : "?";
        url = paramStr != null && paramStr.equals("") ? url + splitChar + paramStr : url;
        return url;
    }
}
